#include "Config.h"
#include "Log.h"
#include "GetOpt.h"
#include "Common.h"


string CConfig::orig_seq_file = "orig_seq_file.yuv";
string CConfig::rec_seq_file = "rec_seq_file.yuv";
string CConfig::pattern_file = "pattern_coff_list.txt";
string CConfig::log_file = "log.txt";
CSeq * CConfig::seq = NULL;
int CConfig::encode_count = 5;
int CConfig::frame_width = 352;
int CConfig::frame_height = 288;
CConfig * CConfig::m_pConfig = NULL;
unsigned int CConfig::time_slice = 30;
bool CConfig::run_once = false;
bool CConfig::run_full_pattern = false;
bool CConfig::use_6tap = false;
bool CConfig::use_4tap = false;
bool CConfig::use_dir_inter = false;
bool CConfig::use_pattern_coff = false;
bool CConfig::run_pattern_static = false;
bool CConfig::no_mirror = false;
unsigned int CConfig::pattern_mask = 0xFFFFF; 
char CConfig::pattern_mask_array[REF_PIXEL_NUMBER];



CConfig::CConfig()
{
	PatternIntToArray( pattern_mask, pattern_mask_array );
}

CConfig * CConfig::GetConfig()
{
	if ( m_pConfig == NULL )
	{
		m_pConfig = new CConfig();
	}

	return m_pConfig;
}


bool CConfig::DumpConfig()
{
	CLog * log = CLog::GetInstance();

	log->log_stream << "========= Dump Config =========" << endl;
	log->log_stream << "Orig Seq File = " << orig_seq_file << endl;
	log->log_stream << "Rec Seq File  = " << rec_seq_file << endl;
	log->log_stream << "Pattern File  = " << pattern_file << endl;
	log->log_stream << "Log File      = " << log_file << endl;
	log->log_stream << endl;
	log->log_stream << "Time Slice    = " << time_slice << endl;		// in seconds
	log->log_stream << "Frame Width   = " << frame_width << endl;
	log->log_stream << "Frame Height  = " << frame_height << endl;
	log->log_stream << "Encoude Count = " << encode_count << endl;
	log->log_stream << endl;
	log->log_stream << "Run Once      = " << run_once << endl;
	log->log_stream << "Run Full Ptn  = " << run_full_pattern << endl;
	log->log_stream << "Use 6 Tap     = " << use_6tap << endl;
	log->log_stream << "Use 4 Tap     = " << use_4tap << endl;
	log->log_stream << "Use Direct Int= " << use_dir_inter << endl;
	log->log_stream << "Use Ptn Coff  = " << use_pattern_coff << endl;
	log->log_stream << "Pattern Static= " << run_pattern_static << endl;
	log->log_stream << endl;
	log->log_stream << "Pattern Mask  = " << hex << pattern_mask << dec << endl;
	log->log_stream << "No Mirror     = " << no_mirror << endl;
	log->log_stream << endl;

	return true;
}


int CConfig::GetConfigFromArgs( int argc, _TCHAR* argv[] )
{

	int c;
	char ** argv_char = new char*[argc];

	for( int i=0; i<argc; i++ )
	{
		argv_char[i] = new char[100];
		wstr2cstr( argv[i], argv_char[i], 100 );

	}

	CConfig * config = CConfig::GetConfig();
	int count;

	while (1)
	{
		c = getopt (argc, argv_char, "r:i:o:p:c:t:hW:H:164dm:sfun");
		if (c == -1)
			break;

		switch (c)
		{
		case 'r':
			cout << "Args: rec_file=" << optarg << endl;
			config->rec_seq_file.assign( optarg );
			break;
		case 'i':
			cout << "Args: orig_file=" << optarg << endl;
			config->orig_seq_file.assign( optarg );
			break;
		case 'o':
			cout << "Args: log_file=" << optarg << endl;
			config->log_file.assign( optarg );
			break;
		case 'p':
			cout << "Args: pattern_file=" << optarg << endl;
			config->pattern_file.assign( optarg );
			break;
		case 'c':
			cout << "Args: encode_count=" << optarg << endl;
			count = atoi( optarg );
			config->encode_count = count;
			break;

		case 't':
			cout << "Args: time_slice=" << optarg << endl;
			count = atoi( optarg );
			config->time_slice = count;
			break;

		case 'W':
			cout << "Args: frame_width=" << optarg << endl;
			count = atoi( optarg );
			config->frame_width = count;
			break;

		case 'H':
			cout << "Args: frame_height=" << optarg << endl;
			count = atoi( optarg );
			config->frame_height = count;
			break;

		case '1':
			cout << "Args: run_once=true" << endl;
			config->run_once = true;
			break;

		case 'f':
			cout << "Args: run_full_pattern=true" << endl;
			config->run_full_pattern = true;
			break;

		case '6':
			cout << "Args: use_6tap=true" << endl;
			config->use_6tap = true;
			break;

		case '4':
			cout << "Args: use_4tap=true" << endl;
			config->use_4tap = true;
			break;

		case 'd':
			cout << "Args: use_dir_inter=true" << endl;
			config->use_dir_inter = true;
			break;

		case 'u':
			cout << "Args: use_pattern_coff=true" << endl;
			config->use_pattern_coff = true;
			break;

		case 'm':
			cout << "Args: pattern_mask=" << optarg << endl;
			if ( strncmp( optarg, "0x", 2 ) == 0 )
			{
				// hex mode
				count = strtol( optarg, NULL, 16 );
			}
			else
			{
				// dec mode
				count = atoi( optarg );
			}
			config->pattern_mask = count;
			break;

		case 's':
			cout << "Args: run_pattern_static=true" << endl;
			config->run_pattern_static = true;
			break;

		case 'n':
			cout << "Args: no_mirror=true" << endl;
			config->no_mirror = true;
			break;

		case 'h':
			ShowHelp();
			break;

		default:
			ShowHelp();
		}
	}


	if (optind < argc)
	{
		printf ("non-option ARGV-elements: ");
		while (optind < argc)
			printf ("%s ", argv[optind++]);
		printf ("\n");

		ShowHelp();
	}

	delete [] argv_char;
	return 0;
}


char * CConfig::W2C(const wchar_t *pw , char *pc)
{
	//*pc++ = *pw >> 8 ;
	*pc = *pw;
	return 0 ;
}

char * CConfig::wstr2cstr(const wchar_t *pwstr , char *pcstr, size_t len)
{
	char *ptemp = pcstr ;
	if(pwstr!=NULL && pcstr!=NULL)
	{

		size_t wstr_len = wcslen(pwstr) ;
		len = (len > wstr_len ) ?    wstr_len : len ;
		while( len-- > 0)
		{
			W2C(pwstr , pcstr);
			pwstr++ ;
			pcstr++ ;
		}
		*pcstr = '\0';
		return ptemp ;
	}
	return 0 ;
}    



void CConfig::ShowHelp()
{
	cout << "Usage: AutoCoffCalc.exe [-r <rec_file>] [-i <orig_file>] [-p <pattern_file>] [-o <log_file>]" << endl;
	cout << "                        [-c <encode_count>] [-W <frame_width>] [-H <frame_height>]" << endl;
	cout << "                        [-t <time_slice_in_seconds>] [-h] [-1] [-6] [-d] [-m pattern_mask] [-u] [-n]" << endl;
	exit(0);
}
